package com.mybatis.service.impl;

import cn.hutool.core.io.FileUtil;
import com.alibaba.druid.pool.DruidDataSource;
import com.mybatis.constant.Constants;
import com.mybatis.constant.DataSourceConstants;
import com.mybatis.dto.request.CodeGenerationParam;
import com.mybatis.dto.request.DatabaseParam;
import com.mybatis.strategy.DatabaseStrategy;
import com.mybatis.template.AbstractGeneratorTemplate;
import com.mybatisflex.codegen.Generator;
import com.mybatisflex.codegen.config.GlobalConfig;
import com.mybatisflex.codegen.dialect.JdbcTypeMapping;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.Date;

/**
 * @desc: 使用mybatis-flex生成代码
 * @projectName: mybatis-generator-parent
 * @author: xhs
 * @date: 2023-7-22 022 17:48
 * @version: JDK 1.8
 */
@Slf4j
@Service("mybatis-flex")
public class MybatisFlexCodeImpl extends AbstractGeneratorTemplate {

    /**
     * 生成代码
     *
     * @param codeGenerationParam 生成代码入参
     * @return boolean
     */
    @Override
    protected boolean getGenerator(CodeGenerationParam codeGenerationParam, DatabaseStrategy databaseStrategy) {
        // 配置数据源
        DatabaseParam databaseParam = new DatabaseParam();
        databaseParam.setDataBaseUrl(codeGenerationParam.getDataBaseUrl());
        databaseParam.setDataBasePort(codeGenerationParam.getDataBasePort());
        databaseParam.setDataBaseName(codeGenerationParam.getDataBaseName());
        databaseParam.setDataBaseUserName(codeGenerationParam.getDataBaseUserName());
        databaseParam.setDataBasePassword(codeGenerationParam.getDataBasePassword());
        DruidDataSource dataSource = databaseStrategy.setDataSource(databaseParam);

        // 数据库地址， 在 MySQL 或者 Oracle 的某些版本中，代码生成器可能无法获取 表 或者 字段 的注释内容，
        // MySQL  在JdbcUrl 上添加 useInformationSchema=true 配置
        // Oracle 在JdbcUrl 上添加 remarksReporting=true 配置
        //判断数据库类型
        if (DataSourceConstants.MYSQL.equals(codeGenerationParam.getDataBaseType())) {
            dataSource.setUrl(dataSource.getUrl()+"?useInformationSchema=true");
        }
        if (DataSourceConstants.ORACLE.equals(codeGenerationParam.getDataBaseType())) {
            dataSource.setUrl(dataSource.getUrl()+"?remarksReporting=true");
        }

        // 创建配置内容
        GlobalConfig globalConfig = createConfigStyle(codeGenerationParam);
        //通过 datasource 和 globalConfig 创建代码生成器
        Generator generator = new Generator(dataSource, globalConfig);
        // 自定义字段类型
        JdbcTypeMapping.registerMapping(LocalDateTime.class, Date.class);
        JdbcTypeMapping.registerMapping(Timestamp.class, Date.class);
        JdbcTypeMapping.registerMapping(java.sql.Date.class, Date.class);
        //生成代码
        generator.generate();
        return true;
    }

    /**
     * 创建配置内容
     *
     * @param codeGenerationParam 创建配置内容的入参
     * @return GlobalConfig
     */
    public static GlobalConfig createConfigStyle(CodeGenerationParam codeGenerationParam) {
        // 创建配置内容
        GlobalConfig globalConfig = new GlobalConfig();
        // 项目根目录
        String projectPath = System.getProperty(Constants.USER_DIR);
        // 文件输出目录
        String outFilePath = projectPath + Constants.FILE_OUTPUT_DIR;
        Path dirPath = Paths.get(outFilePath);
        if (FileUtil.exists(dirPath, true)) {
            // 删除文件夹
            FileUtil.del(dirPath);
        }
        // 创建文件夹
        FileUtil.mkdir(dirPath);

        // 设置作者
        globalConfig.getJavadocConfig()
                .setAuthor(codeGenerationParam.getAuthor());

        // 文件输出目录 及 设置根包
        globalConfig.getPackageConfig()
                .setBasePackage(codeGenerationParam.getBasePackage())
                .setSourceDir(outFilePath);

        // 设置xml文件生成的位置
        String mapperPackage = globalConfig.getMapperPackage();
        String replace = mapperPackage.replace(".", "/");
        String xmlPath = globalConfig.getSourceDir() + "/" + replace;
        globalConfig.getPackageConfig()
                .setMapperXmlPath(xmlPath + "/xml");
        // 设置表前缀和只生成哪些表，setGenerateTable 未配置时，生成所有表
        globalConfig.getStrategyConfig()
                .setGenerateTable(codeGenerationParam.getDataBaseTableName().split(","));

        // 设置生成 entity 并启用 Lombok
        globalConfig.enableEntity()
                .setWithLombok(true)
                .setClassSuffix("Entity")
                .setOverwriteEnable(true);

        //设置生成 mapper
        globalConfig.enableMapper()
                .setClassSuffix("Mapper")
                .setOverwriteEnable(true);

        // 设置生成 MapperXml
        globalConfig.enableMapperXml()
                .setFileSuffix("Mapper")
                .setOverwriteEnable(true);

        // 设置生成Service
        globalConfig.enableService()
                .setOverwriteEnable(true);

        // ServiceImpl
        globalConfig.enableServiceImpl()
                .setOverwriteEnable(true);

        // 设置生成Controller
        globalConfig.enableController()
                .setOverwriteEnable(true);

        return globalConfig;
    }

}
